﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace blackhouse.BlackApart.Data {
    public abstract class AdoPricesDataAccess : IPricesDataAccess {

        #region IPricesDataAccess Members

        public PriceRabatData[] GetPriceRabats(string language, int apartmentTypeId) {
            return this.ReadPriceRabats(this.GetReaderForPriceRabats(language, apartmentTypeId));
        }

        public LengthOfStayModificationData[] GetPriceProfileLengthOfStayModification(int apartmentId) {
            return this.ReadPriceProfileLengthOfStayModification(this.GetReaderForPriceProfileLengthOfStayModification(apartmentId));
        }

        public DateModificationData[] GetPriceProfileDateModification(int apartmentId) {
            return this.ReadPriceProfileDateModification(this.GetReaderForPriceProfileDateModification(apartmentId));
        }

        public VariantLineData[] GetPriceProfileVariants(int apartmentId) {
            return this.ReadPriceProfileVariants(this.GetReaderForPriceProfileVariants(apartmentId));
        }

        public ApartmentPriceData[] GetPriceModifiers(int apartmentId) {
            return this.ReadPrices(this.GetReaderForPrices(apartmentId));
        }

        public abstract double GetApartmentPrice(int apartmentId);

        public ApartmentPrice GetApartmentDbPrice(DateTime startDate, DateTime endDate, int apartmentId, int peopleCount) {
            return this.ReadDbPrice(this.GetReaderForApartmentDbPrice(startDate, endDate, apartmentId, peopleCount));
        }

        #endregion

        #region Abstracts

        protected abstract IDataReader GetReaderForPriceRabats(string language, int apartmentTypeId);
        protected abstract IDataReader GetReaderForApartmentDbPrice(DateTime startDate, DateTime endDate, int apartmentId, int peopleCount);
        protected abstract IDataReader GetReaderForPrices(int apartmentId);
        protected abstract IDataReader GetReaderForPriceProfileVariants(int apartmentId);
        protected abstract IDataReader GetReaderForPriceProfileDateModification(int apartmentId);
        protected abstract IDataReader GetReaderForPriceProfileLengthOfStayModification(int apartmentId);

        #endregion

        #region Methods

        private PriceRabatData[] ReadPriceRabats(IDataReader reader) {
            List<PriceRabatData> data = new List<PriceRabatData>();
            while (reader.Read()) {
                data.Add(this.ReadPriceRabatFields(reader));
            }
            reader.Close();
            return data.ToArray();
        }

        private PriceRabatData ReadPriceRabatFields(IDataReader reader) {
            PriceRabatData data = new PriceRabatData();
            data.RabatKey = Convert.ToString(reader["RabatKey"]);
            data.RabatName = Convert.ToString(reader["RabatName"]);
            data.RabatValue = Convert.ToSingle(reader["RabatValue"]);
            return data;
        }

        private LengthOfStayModificationData[] ReadPriceProfileLengthOfStayModification(IDataReader reader) {
            List<LengthOfStayModificationData> data = new List<LengthOfStayModificationData>();
            while (reader.Read()) {
                data.Add(this.ReadPriceProfileLengthOfStayModificationFields(reader));
            }
            reader.Close();
            return data.ToArray();
        }

        private LengthOfStayModificationData ReadPriceProfileLengthOfStayModificationFields(IDataReader reader) {
            LengthOfStayModificationData data = new LengthOfStayModificationData();
            data.LengthOfStayGreaterOrEqual = Convert.ToInt32(reader["LengthOfStayGreaterOrEqual"]);
            data.LengthOfStayLess = Convert.ToInt32(reader["LengthOfStayLess"]);
            data.ModificationType = Convert.ToString(reader["ModificationType"]);
            data.ModificationValue = Convert.ToDouble(reader["ModificationValue"]);
            return data;
        }

        private DateModificationData[] ReadPriceProfileDateModification(IDataReader reader) {
            List<DateModificationData> data = new List<DateModificationData>();
            while (reader.Read()) {
                data.Add(this.ReadPriceProfileDateModificationFields(reader));
            }
            reader.Close();
            return data.ToArray();
        }

        private DateModificationData ReadPriceProfileDateModificationFields(IDataReader reader) {
            DateModificationData data = new DateModificationData();
            data.RangeToStartReservationFrom = Convert.ToInt32(reader["RangeToStartReservationFrom"]);
            data.RangeToStartReservationTo = Convert.ToInt32(reader["RangeToStartReservationTo"]);
            data.ModificationType = Convert.ToString(reader["ModificationType"]);
            data.ModificationValue = Convert.ToDouble(reader["ModificationValue"]);
            return data;
        }

        private VariantLineData[] ReadPriceProfileVariants(IDataReader reader) {
            List<VariantLineData> data = new List<VariantLineData>();
            while (reader.Read()) {
                data.Add(this.ReadPriceProfileVariantFields(reader));
            }
            reader.Close();
            return data.ToArray();
        }

        private VariantLineData ReadPriceProfileVariantFields(IDataReader reader) {
            VariantLineData data = new VariantLineData();
            data.DefaultPrice = Convert.ToDouble(reader["DefaultPrice"]);
            data.DisableRestModifications = Convert.ToBoolean(reader["DisableRestModifications"]);
            if (!reader.IsDBNull(reader.GetOrdinal("FromDate")))
                data.FromDate = Convert.ToDateTime(reader["FromDate"]);
            else
                data.FromDate = DateTime.MinValue;
            if (!reader.IsDBNull(reader.GetOrdinal("FromDate")))
                data.ToDate = Convert.ToDateTime(reader["ToDate"]);
            else
                data.ToDate = DateTime.MaxValue;
            data.PeopleCount = Convert.ToInt32(reader["PeopleCount"]);
            data.Price = Convert.ToDouble(reader["Price"]);
            if (!reader.IsDBNull(reader.GetOrdinal("FromDate")))
                data.ToDate = Convert.ToDateTime(reader["ToDate"]);
            data.VariantId = Convert.ToInt32(reader["VariantId"]);
            return data;
        }

        private ApartmentPriceData[] ReadPrices(IDataReader reader) {
            List<ApartmentPriceData> data = new List<ApartmentPriceData>();
            while (reader.Read()) {
                data.Add(this.ReadPriceFields(reader));
            }
            reader.Close();
            return data.ToArray();
        }

        private ApartmentPriceData ReadPriceFields(IDataReader reader) {
            ApartmentPriceData data = new ApartmentPriceData();
            data.ValueFrom = Convert.ToInt32(reader["ValueFrom"]);
            data.ValueTo = Convert.ToInt32(reader["ValueTo"]);
            data.ValueEquals = Convert.ToInt32(reader["ValueEquals"]);
            data.ChangeType = Convert.ToString(reader["ChangeType"]);
            data.ClassDeclaration = Convert.ToString(reader["ClassDeclaration"]);
            data.ChangeValue = Convert.ToDouble(reader["ChangeValue"]);
            return data;
        }

        private ApartmentPrice ReadDbPrice(IDataReader reader) {
            ApartmentPrice data = new ApartmentPrice();
            if (reader.Read()) {
                data = this.ReadDbPriceFields(reader);
            }
            reader.Close();
            return data;
        }

        private ApartmentPrice[] ReadDbPrices(IDataReader reader) {
            List<ApartmentPrice> data = new List<ApartmentPrice>();
            while (reader.Read()) {
                data.Add(this.ReadDbPriceFields(reader));
            }
            reader.Close();
            return data.ToArray();
        }

        private ApartmentPrice ReadDbPriceFields(IDataReader reader) {
            ApartmentPrice data = new ApartmentPrice();
            data.DayCount = Convert.ToInt32(reader["DayCount"]);
            data.Price = Convert.ToDouble(reader["Price"]);
            //data.PriceWithoutRabat = Convert.ToDouble(reader["PriceWithoutRabat"]);
            //data.Rabat = Convert.ToSingle(reader["Rabat"]);
            return data;
        }

        #endregion

    }
}
